"""
锁定系统
处理单位间的探测、锁定、消灭逻辑

作者：wjttdbx
版本：3.0 - 重构版本
"""
import sys
sys.path.insert(0, sys.path[0]+"/../")

import math
from typing import List, Optional, TYPE_CHECKING
from .config import GameConfig

if TYPE_CHECKING:
    from .units import Unit, WhiteBoat, WhiteDrone, BlackBoat


class LockingSystem:
    """
    锁定系统
    处理单位间的探测、锁定、消灭逻辑
    """
    
    @staticmethod
    def update_white_boat_detection(white_boat: 'WhiteBoat', black_boats: List['BlackBoat']):
        """
        更新白方无人艇的探测目标列表（仅无人船自身探测）
        
        Args:
            white_boat (WhiteBoat): 白方无人艇
            black_boats (List[BlackBoat]): 黑方无人艇列表
        """
        white_boat.detected_targets = []
        
        # 白方无人艇自身探测
        for target in black_boats:
            if target.active and white_boat.distance_to(target) <= GameConfig.WHITE_BOAT_DETECT_RANGE:
                white_boat.detected_targets.append(target)
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{white_boat.id} 探测到目标{target.id}: 距离={white_boat.distance_to(target):.0f}m")

    @staticmethod
    def update_white_drone_detection(white_drone: 'WhiteDrone', black_boats: List['BlackBoat']):
        """
        更新白方无人机的探测目标列表
        
        Args:
            white_drone (WhiteDrone): 白方无人机
            black_boats (List[BlackBoat]): 黑方无人艇列表
        """
        white_drone.detected_targets = []
        
        for target in black_boats:
            if target.active:
                distance = white_drone.distance_to(target)
                # 首先检查距离是否在探测范围内
                if distance <= GameConfig.WHITE_DRONE_DETECT_RANGE:
                    # 然后检查是否在60°扇形内
                    in_sector = white_drone.is_target_in_detection_sector(target, white_drone.heading)
                    
                    # 详细调试信息
                    target_angle = math.atan2(target.y - white_drone.y, target.x - white_drone.x)
                    if GameConfig.debug_mode:
                      # 仅在调试模式下打印探测到的目标
                        print(f"[LockingSystem] 无人机{white_drone.id} 检测目标{target.id}: "
                            f"距离={distance:.0f}m, "
                            f"无人机位置=({white_drone.x:.0f}, {white_drone.y:.0f}), "
                            f"目标位置=({target.x:.0f}, {target.y:.0f}), "
                            f"无人机朝向={math.degrees(white_drone.heading):.1f}°, "
                            f"目标角度={math.degrees(target_angle):.1f}°, "
                            f"在扇形内={in_sector}")
                    
                    if in_sector:
                        white_drone.detected_targets.append(target)
                        if GameConfig.debug_mode:
                            # 仅在调试模式下打印探测到的目标
                            print(f"[LockingSystem] 无人机{white_drone.id} 探测到目标{target.id}")
                else:
                    if GameConfig.debug_mode:
                        print(f"[LockingSystem] 目标{target.id} 距离无人机{white_drone.id} 太远: {distance:.0f}m > {GameConfig.WHITE_DRONE_DETECT_RANGE}m")

    @staticmethod
    def update_white_boat_detection_legacy(white_boat: 'WhiteBoat', black_boats: List['BlackBoat'], white_drones: List['WhiteDrone'], current_time: Optional[float] = None):
        """
        更新白方无人艇的探测目标列表（原有的混合方法，保留兼容性）
        
        Args:
            white_boat (WhiteBoat): 白方无人艇
            black_boats (List[BlackBoat]): 黑方无人艇列表
            white_drones (List[WhiteDrone]): 白方无人机列表
            current_time (float): 当前时间，用于检查冻结状态
        """
        LockingSystem._update_white_detection_logic(white_boat, black_boats, white_drones, current_time)

    @staticmethod
    def update_black_boat_detection(boat: 'BlackBoat', white_boats: List['WhiteBoat']):
        """
        更新黑方无人艇的探测目标列表（黑方无法探测/锁定无人机）

        Args:
            boat (BlackBoat): 黑方无人艇
            white_boats (List[WhiteBoat]): 白方无人艇列表
        """
        LockingSystem._update_black_detection_logic(boat, white_boats)

    @staticmethod
    def _update_white_detection_logic(white_boat: 'WhiteBoat', targets: List['BlackBoat'], 
                                     drones: Optional[List['WhiteDrone']] = None, current_time: Optional[float] = None):
        """更新白方探测逻辑"""
        white_boat.detected_targets = []
        
        # 白方无人艇自身探测
        for target in targets:
            if target.active:
                # 如果目标处于冻结状态，直接加入探测列表（不需要距离检查）
                # 如果目标未冻结，需要检查探测距离
                should_detect = False
                detection_reason = ""
                
                if current_time is not None and target.is_frozen(current_time):
                    should_detect = True
                    detection_reason = "冻结状态强制探测"
                elif white_boat.distance_to(target) <= GameConfig.WHITE_BOAT_DETECT_RANGE:
                    should_detect = True
                    detection_reason = "距离探测"
                
                if should_detect:
                    white_boat.detected_targets.append(target)
                    if GameConfig.debug_mode:
                        frozen_status = ""
                        if current_time is not None and target.is_frozen(current_time):
                            frozen_status = " (冻结中)"
                # print(f"[LockingSystem] 无人艇{white_boat.id} 自身探测到目标{target.id}: 距离={white_boat.distance_to(target):.0f}m{frozen_status} - {detection_reason}")

        
        # 无人机信息共享
        if drones:
            detected_by_drones = set()
            for drone in drones:
                if drone.state == "flying":
                    # 更新无人机自身的探测列表
                    drone.detected_targets = []
                    
                    for target in targets:
                        if target.active:
                            distance = drone.distance_to(target)
                            # 如果目标处于冻结状态，直接加入探测列表（不需要距离和扇形检查）
                            # 如果目标未冻结，需要检查探测距离和扇形
                            should_detect = False
                            detection_reason = ""
                            
                            if current_time is not None and target.is_frozen(current_time):
                                should_detect = True
                                detection_reason = "冻结状态强制探测"
                            elif distance <= GameConfig.WHITE_DRONE_DETECT_RANGE:
                                # 然后检查是否在60°扇形内
                                in_sector = drone.is_target_in_detection_sector(target, drone.heading)
                                if in_sector:
                                    should_detect = True
                                    detection_reason = "距离+扇形探测"
                            
                            if should_detect:
                                drone.detected_targets.append(target)
                                detected_by_drones.add(target.id)
                                if GameConfig.debug_mode:
                                    frozen_status = ""
                                    if current_time is not None and target.is_frozen(current_time):
                                        frozen_status = " (冻结中)"
                    # print(f"[LockingSystem] 无人机{drone.id} 探测到目标{target.id}: 距离={distance:.0f}m{frozen_status} - {detection_reason}")

            
            # 将无人机探测到的目标加入到白方无人艇的探测列表
            for target in targets:
                if target.active and target.id in detected_by_drones:
                    if target not in white_boat.detected_targets:
                        white_boat.detected_targets.append(target)
                        if GameConfig.debug_mode:
                            frozen_status = ""
                            if current_time is not None and target.is_frozen(current_time):
                                frozen_status = " (冻结中)"
                            print(f"📡 [LockingSystem] 无人艇{white_boat.id} 通过无人机共享获得目标{target.id}{frozen_status}")

        

    @staticmethod
    def _update_black_detection_logic(black_boat: 'BlackBoat', targets: List['WhiteBoat']):
        """更新黑方探测逻辑"""
        black_boat.detected_targets = []
        for target in targets:
            if target.active and black_boat.distance_to(target) <= GameConfig.BLACK_BOAT_DETECT_RANGE:
                black_boat.detected_targets.append(target)

    @staticmethod
    def try_white_boat_lock(boat: 'WhiteBoat', target_id: int,current_time: float) -> bool:
        """
        尝试白方无人艇锁定目标
        
        锁定判定逻辑：
        1. 初次锁定：目标必须在探测范围内（20km），或者在无人机探测范围内
        2. 持续锁定：目标只需在锁定范围内（40km），不需要探测条件
        3. 目标切换：新目标必须在探测范围内（20km）
        
        Args:
            boat (WhiteBoat): 白方无人艇
            target_id (int): 目标ID
            current_time (float): 当前时间
            
        Returns:
            bool: 是否成功锁定
        """
        aim_target = None
        
        # 检查是否是持续锁定（当前正在锁定同一个目标）
        if boat.is_locking and boat.current_target and boat.current_target.id == target_id:
            # 持续锁定：只需要检查锁定范围，不需要探测条件
            distance = boat.distance_to(boat.current_target)
            if distance <= GameConfig.WHITE_BOAT_LOCK_RANGE:
                aim_target = boat.current_target
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} 持续锁定目标 unit_id={target_id}: 距离={distance:.0f}m <= {GameConfig.WHITE_BOAT_LOCK_RANGE}m")
            else:
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} 持续锁定目标 unit_id={target_id} 超出锁定范围: 距离={distance:.0f}m > {GameConfig.WHITE_BOAT_LOCK_RANGE}m")
                boat.stop_locking()
                return False
        # 检查是否是FSM代理已经设置的目标（但还未开始锁定）
        elif boat.current_target and boat.current_target.id == target_id:
            # FSM代理已经设置了目标，需要检查是否真的被探测到以及在锁定范围内
            distance = boat.distance_to(boat.current_target)
            
            # 首先检查目标是否在探测列表中（是否真的被探测到）
            target_detected = any(target.id == target_id for target in boat.detected_targets)
            if not target_detected:
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} FSM代理设置的目标 unit_id={target_id} 未被探测到")
                return False
            
            # 然后检查是否在锁定范围内
            if distance <= GameConfig.WHITE_BOAT_LOCK_RANGE:
                aim_target = boat.current_target
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} FSM代理设置的目标 unit_id={target_id} 已被探测到且在锁定范围内: 距离={distance:.0f}m <= {GameConfig.WHITE_BOAT_LOCK_RANGE}m")
            else:
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} FSM代理设置的目标 unit_id={target_id} 已被探测到但超出锁定范围: 距离={distance:.0f}m > {GameConfig.WHITE_BOAT_LOCK_RANGE}m")
                return False
        else:
            # 初次锁定或目标切换：需要探测条件
            if not boat.detected_targets:
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} 没有探测到任何目标")
                boat.stop_locking()
                return False
            
            if GameConfig.debug_mode:
                print(f"[LockingSystem] 无人艇{boat.id} 探测到 {len(boat.detected_targets)} 个目标")
            
            # 检查目标是否可以锁定
            for target in boat.detected_targets:
                if target.id == target_id:
                    distance = boat.distance_to(target)
                    
                    # 初次锁定：目标已被探测（含无人机共享），允许在40km内直接开始锁定
                    # 目标切换：仍要求20km探测范围
                    if not boat.is_locking:
                        range_required = GameConfig.WHITE_BOAT_LOCK_RANGE
                        lock_type = "初次锁定"
                    else:
                        range_required = GameConfig.WHITE_BOAT_DETECT_RANGE
                        lock_type = "目标切换"
                    
                    if distance <= range_required:
                        aim_target = target
                        if GameConfig.debug_mode:
                            print(f"[LockingSystem] 无人艇{boat.id} {lock_type}目标 unit_id={target.id} 在探测范围内: 距离={distance:.0f}m <= {range_required}m")
                    else:
                        if GameConfig.debug_mode:
                            print(f"[LockingSystem] 无人艇{boat.id} {lock_type}目标 unit_id={target.id} 超出探测范围: 距离={distance:.0f}m > {range_required}m")
                        return False
                    break
        
        if aim_target is not None:
            # 开始或继续锁定
            if not boat.is_locking:
                boat.lock_start_time = current_time
                boat.is_locking = True
                boat.start_locking(aim_target, current_time)
                if GameConfig.debug_mode:
                    print(f"[LockingSystem] 无人艇{boat.id} 开始锁定目标 unit_id={aim_target.id}")
           
            # 检查是否锁定成功（持续300秒不间断，80%概率成功）
            lock_duration = boat.get_lock_duration(current_time)
            can_succeed = LockingSystem.can_lock_successfully(boat, current_time, 
                                            GameConfig.WHITE_BOAT_LOCK_DURATION,
                                            GameConfig.WHITE_BOAT_LOCK_SUCCESS_RATE)
            
            if GameConfig.debug_mode:
                print(f"[LockingSystem] 无人艇{boat.id} 锁定目标 unit_id={aim_target.id}: 持续时间={lock_duration:.1f}s/{GameConfig.WHITE_BOAT_LOCK_DURATION}s, 可成功={can_succeed}")
            
            if can_succeed:
                # 锁定成功处理
                print(f" [LockingSystem] 无人艇{boat.id} 成功锁定目标 unit_id={aim_target.id}")
                LockingSystem.apply_lock_success(aim_target, current_time)
                boat.stop_locking()
                return True
            else:
                # 正在锁定中，但还未成功
                return True
        
        return False
    
    @staticmethod
    def try_black_boat_lock(boat: 'BlackBoat', current_time: float) -> bool:
        """
        尝试黑方无人艇锁定目标
        
        Args:
            boat (BlackBoat): 黑方无人艇
            current_time (float): 当前时间
            
        Returns:
            bool: 是否成功锁定
        """
        if not boat.detected_targets:
            boat.stop_locking()
            return False
        
        # 选择最近的目标
        target = min(boat.detected_targets, key=lambda t: boat.distance_to(t))
        
        # 检查距离是否在锁定范围内
        if LockingSystem.is_target_in_lock_range(boat, target, GameConfig.BLACK_BOAT_LOCK_RANGE):
            # 开始或继续锁定
            boat.start_locking(target, current_time)
            
            # 检查是否锁定成功
            if LockingSystem.can_lock_successfully(boat, current_time, 
                                                 GameConfig.BLACK_BOAT_LOCK_DURATION,
                                                 GameConfig.BLACK_BOAT_LOCK_SUCCESS_RATE):
                # 锁定成功
                LockingSystem.apply_lock_success(target, current_time)
                boat.stop_locking()
                return True
        else:
            # 距离超出锁定范围，停止锁定
            if boat.current_target == target:
                boat.stop_locking()
        
        return False
    
    @staticmethod
    def is_target_in_lock_range(boat: 'Unit', target: 'Unit', lock_range: float) -> bool:
        """
        检查目标是否在锁定范围内
        
        Args:
            unit (Unit): 执行锁定的单位
            target (Unit): 目标单位
            lock_range (float): 锁定距离
            
        Returns:
            bool: 目标是否在锁定范围内
        """
        return boat.distance_to(target) <= lock_range

    @staticmethod
    def can_lock_successfully(unit: 'Unit', current_time: float, lock_duration: float = 300, success_rate: float = 0.8) -> bool:
        """
        检查单位是否可以锁定成功
        
        Args:
            unit (Unit): 执行锁定的单位
            current_time (float): 当前时间
            lock_duration (float): 锁定持续时间要求
            success_rate (float): 锁定成功率
            
        Returns:
            bool: 是否可以锁定成功
        """
        if not unit.is_locking or not unit.current_target:
            return False
        
        # 检查锁定时间是否足够
        if unit.get_lock_duration(current_time) >= lock_duration:
            # 概率判定
            import random
            return random.random() < success_rate
        
        return False

    @staticmethod
    def apply_lock_success(target: 'Unit', current_time: float):
        """
        应用锁定成功的效果
        
        Args:
            target (Unit): 被锁定的目标
            current_time (float): 当前时间
        """
        target.locked_times += 1
        target.freeze_until = current_time + GameConfig.FREEZE_DURATION
        
        # 检查是否消灭目标（第二次锁定成功）
        if target.locked_times >= GameConfig.MAX_LOCKS_TO_ELIMINATE:
            target.active = False  # 永久失效
            
            # 清理所有正在锁定这个目标的无人艇的current_target
            from sh15.core.CoreEnvironment import CoreEnvironment
            # 这里我们需要访问CoreEnvironment来清理无人艇状态
            # 但是由于这是静态方法，我们需要通过其他方式处理
            # 在FSM代理的_handle_target_destroyed方法中已经处理了清理逻辑